from fastapi import FastAPI, Query, UploadFile, File, HTTPException, Form
from fastapi.responses import JSONResponse, StreamingResponse, RedirectResponse
import uvicorn
from dbutils.pooled_db import PooledDB
import pymysql
import socket
import time
import os
import gc  # 添加垃圾回收模块导入
import datetime
import enum
import configparser
import logging
import signal
import sys
import traceback
from typing import List, Optional, Dict, Any
from utils import get_mysql_conn,initialize
from logging_config import setup_logger, get_logger
import file_operations
import folder_operations
import corp_operations
import system

# 定义全局变量
CONFIG = None
ROOTPATH = None
mysql_pool = None
dbmgmt = None  # 全局DBUtilsTest实例


class DBUtilsTest:
    def __init__(self, test_name="Default Test"):
        self.test_name = test_name
        self.mysql_pool = None
        print(f"=== Starting test: {self.test_name} ===")
    
    def get_connection_pool(self):
        """获取当前初始化的连接池"""
        if self.mysql_pool:
            print(f"Returning connection pool: {type(self.mysql_pool)}")
            return self.mysql_pool
        else:
            print("Connection pool not initialized, cannot return")
            return None
    
    def release_connection_pool(self):
        """释放连接池资源并将实例连接池设置为None"""
        self.cleanup_pool()
        print("Connection pool released from DBUtilsTest instance")
    
    def initialize_pool(self):
        """初始化数据库连接池"""
        try:
            # 自定义连接创建函数
            def create_connection():
                conn = pymysql.connect(
                    host=CONFIG['mysql']['host'],
                    port=int(CONFIG['mysql']['port']),
                    user=CONFIG['mysql']['user'],
                    password=CONFIG['mysql']['password'],
                    database=CONFIG['mysql']['database'],                   
                    connect_timeout=10,  # 增加连接超时时间
                    read_timeout=30,
                    write_timeout=30,
                    charset='utf8mb4',  # 指定字符集
                    cursorclass=pymysql.cursors.DictCursor  # 使用字典游标
                )
                return conn
            
            # 创建连接池 - 优化参数以适应快速重启场景
            self.mysql_pool = PooledDB(
                creator=create_connection,
                maxconnections=3,  # 减少最大连接数
                mincached=0,  # 最小缓存连接设为0，避免资源占用
                maxcached=2,  
                maxshared=0,
                blocking=True,
                maxusage=None,
                setsession=["SET SESSION time_zone = '+0:00'"],
                ping=1,  # 保持连接活跃
                reset=True  # 重置连接状态
            )
            print("Connection pool initialized successfully")
            return True
        except Exception as e:
            print(f"Failed to initialize connection pool: {e}")
            self.mysql_pool = None
            return False
    
    def test_connection(self):
        """测试连接是否正常"""
        if not self.mysql_pool:
            print("Connection pool is not initialized")
            return False
        
        try:
            # 从连接池获取连接
            conn = self.mysql_pool.connection()
            cursor = conn.cursor()
            cursor.execute("SELECT * FROM corps")
            result = cursor.fetchone()
            print(f"Connection test successful: {result}")           
            cursor.close()
            conn.close()
            return True
        except Exception as e:
            print(f"Connection test failed: {e}")
            return False
    
    def cleanup_pool(self):
        """清理连接池资源"""
        if self.mysql_pool:
            print(f"Cleaning up connection pool... (Type: {type(self.mysql_pool)})")
            try:
                # 尝试多种关闭方法
                if hasattr(self.mysql_pool, 'close'):
                    print("Calling close() method")
                    self.mysql_pool.close()
                elif hasattr(self.mysql_pool, '_close'):
                    print("Calling _close() method")
                    self.mysql_pool._close()
                elif hasattr(self.mysql_pool, '_pool') and hasattr(self.mysql_pool._pool, 'closeall'):
                    print("Calling _pool.closeall() method")
                    self.mysql_pool._pool.closeall()
                
                # 等待一小段时间确保连接真正关闭
                time.sleep(0.1)
                print("Connection pool cleanup completed")
            except Exception as e:
                print(f"Error during pool cleanup: {e}")
            finally:
                # 清除引用并进行垃圾回收
                self.mysql_pool = None
                print("Clearing pool reference and collecting garbage")
                # 强制垃圾回收，确保资源释放
                gc.collect()
                gc.collect()  # 再次调用以确保回收

def test_multiple_restarts():
    """测试多次快速重启"""
    print("=== 测试连接池多次快速重启 ===")    
    success_count = 0
    total_tests = 3
    
    for i in range(total_tests):
        print(f"\n--- Restart Cycle {i+1}/{total_tests} ---")
        test = DBUtilsTest(f"Cycle {i+1}")
        if test.initialize_pool():
            if test.test_connection():
                print(f" Cycle {i+1} successful!")
                success_count += 1
            else:
                print(f" Cycle {i+1} connection test failed!")
        else:
            print(f"Cycle {i+1} pool initialization failed!")
        
        # 清理资源
        test.cleanup_pool()
        
        # 短暂延迟（可以调整测试不同延迟）
        if i < total_tests - 1:
            delay = 0.5  # 增加延迟到500ms，确保资源充分释放
            print(f"Waiting {delay}s before next cycle...")
            time.sleep(delay)
    
    # 输出结果统计
    print(f"\n--- Multiple Restarts Summary ---")
    print(f"Successful cycles: {success_count}/{total_tests}")
    if success_count == total_tests:
        print(" All restart cycles passed!")
    else:
        print(f"Some restart cycles failed!")

# 信号处理函数
def cleanup_resources(signum, frame):
    """清理资源"""
    logger = logging.getLogger('indsrv')
    logger.info("Starting cleanup process...")
    
    try:
        # 使用全局DBUtilsTest实例释放连接池资源
        global dbmgmt, mysql_pool
        
        # 优先通过DBUtilsTest实例释放资源
        if dbmgmt:
            logger.info("Releasing connection pool through DBUtilsTest instance...")
            try:
                dbmgmt.release_connection_pool()
                logger.info("Connection pool released successfully")
            except Exception as e:
                logger.error(f"Error releasing connection pool: {e}")
        
        # 确保全局变量被重置
        mysql_pool = None
        logger.info("Global mysql_pool reference cleared")
    except Exception as e:
        logger.error(f"Error during resource cleanup: {e}")
        
    # 等待资源释放完成
    time.sleep(0.5)
    logger.info("Cleanup process completed")

    import sys
    sys.exit(0)

# 文件类型枚举定义
class FileType(enum.Enum):
    FOLDER = 0               # 文件夹
    IMAGE = 2                # 图片
    DOCUMENT = 3             # 文档
    AUDIO = 4                # 音频
    OTHER = 5                # 其他
    HIDE_DIRECTORY = 6       # 隐藏目录
    VIDEO = 7                # 视频

# 文件状态标志位枚举定义
class Delflag(enum.Enum):
    NORMAL = 0               # 正常
    DELETED = 1              # 删除
    UPLOADING = 5            # 上传中
    HIDE_DIRECTORY = 6       # 隐藏目录

# 配置文件加载
def load_config():
    """加载配置文件，支持行内注释和多行配置"""
    global CONFIG
    config_path = os.path.join(os.path.dirname(__file__), 'nasind.conf')
    if not os.path.exists(config_path):
        print(f"Configuration file not found: {config_path}")
        return None        
    config = configparser.ConfigParser(inline_comment_prefixes=('#',), allow_no_value=True)
    config.read(config_path, encoding='utf-8')
    # 使用全局变量
    global CONFIG
    CONFIG = {
        "root_dir": os.path.abspath(config['system']['root_dir'].replace('\\', '/')),  # 存储根目录
        "log_dir": os.path.abspath(config['system']['log_dir'].replace('\\', '/')),  # 日志目录
        "log_level": config['system'].get('log_level', 'INFO'),  # 日志级别
        "log_backup_days": int(config['system']['log_backup_days']),  # 日志备份天数
        "srvip": config['system'].get('srvip', '0.0.0.0'),  # 服务IP
        "srvport": int(config['system'].get('srvport', 8181)),  # 服务端口
        "worknum": int(config['system'].get('worknum', 1)),  # 工作进程数
        "mysql": {
            "host": config['mysql']['host'],
            "port": int(config['mysql']['port']),
            "user": config['mysql']['user'],
            "password": config['mysql']['password'],
            "database": config['mysql']['database']
        },
        "edgesrv_list": []
    }
    # 解析边缘服务器列表
    server_list_str = config['edgesrv']['server_list']
    # 处理多行配置 - 替换行连接符并去除多余空白
    server_list_str = server_list_str.replace('\n', ' ').replace('\\\n', ' ').strip()
    for server_info in server_list_str.split(';'):
        if server_info.strip():
            parts = [p.strip() for p in server_info.split(',')]
            if len(parts) == 5:
                # 确保路径格式正确处理斜杠和反斜杠
                path = parts[4]
                # 处理路径中的反斜杠
                if '\\' in path:
                    path = path.replace('\\', '/')
                # 确保路径中不包含末尾的反斜杠
                if path.endswith('/'):
                    path = path[:-1]
                CONFIG['edgesrv_list'].append({
                    "id": int(parts[0]),
                    "ip": parts[1],
                    "netip": parts[2],
                    "port": int(parts[3]),
                    "path": os.path.abspath(path)
                })
                print(f"Added edge server: id={parts[0]}, ip={parts[1]}, port={parts[3]}")
            else:
                print(f"Invalid server configuration format: {server_info}")

    # 设置ROOTPATH
    global ROOTPATH
    ROOTPATH = CONFIG["root_dir"]
    print(f"Loaded {len(CONFIG['edgesrv_list'])} edge servers")
    return CONFIG


# 使用全局logger
logger = get_logger('main')



# 创建MySQL全局企业表 - 存储所有企业的基本信息
def create_mysql_corps_table():
    conn = get_mysql_conn()
    if not conn:
        logger.error("Failed to get MySQL connection for creating corps table")
        return False
    
    try:
        cursor = conn.cursor()
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS corps (
                corpid VARCHAR(20) PRIMARY KEY,
                corpname VARCHAR(100) NOT NULL,
                quota BIGINT NOT NULL DEFAULT 0,
                used BIGINT NOT NULL DEFAULT 0,
                ctime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                mtime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                inuse INT NOT NULL DEFAULT 1
            )
        ''')
        conn.commit()
        logger.info("MySQL corps table created successfully")
        return True
    except Exception as e:
        logger.error(f"Failed to create MySQL corps table: {e}")
        return False
    finally:
        if conn:
            conn.close()

# 创建MySQL企业员工表 - 存储企业员工信息
def create_mysql_employees_table():
    conn = get_mysql_conn()
    if not conn:
        logger.error("Failed to get MySQL connection for creating employees table")
        return False
    
    try:
        cursor = conn.cursor()
        # 表名使用前缀+企业ID，避免多企业数据冲突
        table_name = f"employees"
        cursor.execute(f'''
            CREATE TABLE IF NOT EXISTS {table_name} (
                corpid VARCHAR(20) NOT NULL,
                uid VARCHAR(20) NOT NULL,
                subid VARCHAR(20) NOT NULL,
                nickname VARCHAR(100) NOT NULL,
                passwd VARCHAR(20) NOT NULL,
                deptid VARCHAR(20),
                email VARCHAR(100),
                phone VARCHAR(20),
                inuse INT NOT NULL DEFAULT 1,
                ctime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                mtime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                PRIMARY KEY (corpid, uid),
                INDEX idx_corpid (corpid)
            )
        ''')
        conn.commit()
        logger.info(f"MySQL employees table created successfully for corp: {table_name}")
        return True
    except Exception as e:
        logger.error(f"Failed to create MySQL employees table for corp {table_name}: {e}")
        return False
    finally:
        if conn:
            conn.close()




# 获取路由
file_router = file_operations.file_router
folder_router = folder_operations.folder_router
corp_router = corp_operations.corp_router
system_router = system.system_router

app = FastAPI(title="云存储管理系统indsrv", version="v1")

# 挂载文件操作、文件夹操作和企业操作的路由
app.include_router(file_router)
app.include_router(folder_router)
app.include_router(corp_router)
app.include_router(system_router)

@app.get("/")
async def root():
    return {"message": "云存储管理系统indsrv API服务", "version": "v1"}

@app.get("/health")
async def health_check():
    """健康检查接口"""
    return {"status": "healthy", "timestamp": datetime.datetime.now().isoformat()}

if __name__ == "__main__":    
    # 在顶级作用域中，不需要使用global关键字声明全局变量
    # 注册信号处理函数
    signal.signal(signal.SIGINT, cleanup_resources)  # 处理Ctrl+C
    signal.signal(signal.SIGTERM, cleanup_resources)  # 处理终止信号
    
    # 加载配置
    CONFIG = load_config()
    if CONFIG is None:
        print("Failed to load configuration, exiting...")
        exit(1)
   
    # test_multiple_restarts()    
    #日志    
    log_dir = os.path.abspath(CONFIG['log_dir'].replace('\\', '/'))
    log_level = CONFIG['log_level']
    # 初始化全局日志系统
    root_logger = setup_logger(log_dir, int(CONFIG['log_backup_days']), log_level)
    logger.info("Signal handlers registered successfully")
    # 创建根目录
    os.makedirs(CONFIG["root_dir"], exist_ok=True)
    
    # 创建全局DBUtilsTest实例
    dbmgmt = DBUtilsTest("Main Application Pool")  
    db_test = dbmgmt
    if db_test.initialize_pool():
        mysql_pool = db_test.get_connection_pool()
        if mysql_pool:
            logger.info("全局mysql_pool变量赋值成功!")
        else:
            logger.info(" 全局mysql_pool变量赋值失败!")
    else:
        logger.info(" 连接池初始化失败!")
    # 初始化utils模块，传入配置和MySQL连接池
    if mysql_pool:
        logger.info("\n=== 初始化utils模块 ===")
        initialize(CONFIG, mysql_pool)
        create_mysql_corps_table()
        create_mysql_employees_table()
    else:
        logger.info("连接池未初始化，跳过utils初始化和表创建")   
    
    try:
        # 启动FastAPI应用
        logger.info("Starting FastAPI application...")
        uvicorn.run(
            "main:app",
            host=CONFIG["srvip"],
            port=CONFIG["srvport"],
            workers=CONFIG["worknum"]
        )
    except Exception as app_e:
        logger.error(f"FastAPI application error: {app_e}")
        logger.error(f"Detailed error stack: {traceback.format_exc()}")
    finally:
        # 无论如何都要清理连接池资源
        logger.info("Application shutdown, cleaning up resources...")
        dbmgmt.release_connection_pool()
